package com.xfcy.blog.service.impl;

import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.codec.Base64;
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.xfcy.blog.common.R;
import com.xfcy.blog.common.constant.Constant;
import com.xfcy.blog.common.constant.RedisConstant;
import com.xfcy.blog.common.enums.ResultCode;
import com.xfcy.blog.dto.LoginDTO;
import com.xfcy.blog.entity.User;
import com.xfcy.blog.exception.CustomerException;
import com.xfcy.blog.exception.XfcyException;
import com.xfcy.blog.mapper.UserMapper;
import com.xfcy.blog.service.LoginService;
import com.xfcy.blog.utils.BCryptUtils;
import com.xfcy.blog.utils.UUIDUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.FastByteArrayOutputStream;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * @author 晓风残月Lx
 * @date 2023/5/14 18:07
 */
@Service("loginService")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LoginServiceImpl implements LoginService {

    private final UserMapper userMapper;

    private final RedisTemplate redisTemplate;

    @Resource(name = "getDefaultKaptcha")
    private Producer defaultKaptcha;

    /**
     * 后台登陆
     *
     * @param loginDTO
     * @return
     */
    @Override
    public R login(LoginDTO loginDTO) {
        // 检验验证码
        Object objectCode = redisTemplate.opsForValue().get(RedisConstant.CAPTCHA_CODE + loginDTO.getUuid());
        if (objectCode == null || !objectCode.equals(loginDTO.getCode())) {
            throw new CustomerException("验证码已失效或验证码输入错误!");
        }
        // 检验用户名和密码
        User user = userMapper.selectUserByName(loginDTO.getUsername());
        boolean checkPassword = BCryptUtils.checkPassword(loginDTO.getPassword(), user.getPassword());
        Assert.isTrue(checkPassword, ResultCode.ERROR_PASSWORD.getDesc());

        if (loginDTO.getRememberMe()) {
            StpUtil.login(user.getId().longValue(), new SaLoginModel().setTimeout(60 * 60 * 24 * 7));
        } else {
            StpUtil.login(user.getId().longValue());
        }
        StpUtil.getSession().set(Constant.CURRENT_USER, userMapper.getById(user.getId()));
        return R.success(StpUtil.getTokenValue());
    }

    /**
     * 获取验证码
     * @return
     */
    @Override
    public Map<String, String> captchaImage() throws IOException {
        Map<String, String> result = new HashMap<>();
        // 生成验证码的UUID
        String uuid = UUIDUtils.getUuid();
        String capStr = null;
        String code = null;
        BufferedImage image = null;
        // 生成验证码
        String capText = defaultKaptcha.createText();
        capStr = capText.substring(0, capText.lastIndexOf("@"));
        code = capText.substring(capText.lastIndexOf("@") + 1);
        image = defaultKaptcha.createImage(capStr);

        // 在redis上保存验证码
        redisTemplate.opsForValue().set(RedisConstant.CAPTCHA_CODE + uuid, code, RedisConstant.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);

        // 转换流信息写出
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        ImageIO.write(image, "jpg", os);
        result.put("uuid",uuid);
        result.put("img", Base64.encode(os.toByteArray()));
        return result;
    }


}
